package repository

import (
	"PolarDay/common/logger"
	"PolarDay/models/entitys"
)

type ISysMenuRepo interface {
	GetMenuById(id int32) *entitys.SysMenu
	InsertMenu(menu *entitys.SysMenu) bool
	UpdateMenu(menu *entitys.SysMenu) bool
	DeleteMenu(id int32) bool
	ListMenu(page, size int32, total *int32, where any) []*entitys.SysMenu
	GetMenuByRoleId(roleId int32) []*entitys.SysMenu
	GetMenuIdByRoleId(roleId int32) []int32
	GetMenusByPid(pid int32) []*entitys.SysMenu
	GetMenuIdByUserId(userId int32) []int32
	GetMenuPermByUserId(userId int32) []string
	SaveMenuApi(menuId int32, apiId int32) bool
	DelMenuApi(menuId int32) bool
	GetApiIdByMenuId(menuId int32) []int32
}

type SysMenuRepo struct {
	Log      logger.ILogger `inject:""`
	BaseRepo BaseRepo       `inject:"inline"`
}

func (repo *SysMenuRepo) GetMenuById(id int32) *entitys.SysMenu {
	var menu entitys.SysMenu
	if err := repo.BaseRepo.FirstByID(&menu, int(id)); err != nil {
		repo.Log.Errorf("获取菜单数据失败", err)
	}
	return &menu
}

func (repo *SysMenuRepo) InsertMenu(menu *entitys.SysMenu) bool {
	if err := repo.BaseRepo.Create(menu); err != nil {
		repo.Log.Errorf("新增菜单失败", err)
		return false
	}
	return true
}

func (repo *SysMenuRepo) UpdateMenu(menu *entitys.SysMenu) bool {
	if err := repo.BaseRepo.Source.DB().Model(&menu).Update(menu).Error; err != nil {
		repo.Log.Errorf("更新菜单失败", err)
		return false
	}
	return true
}

func (repo *SysMenuRepo) DeleteMenu(id int32) bool {
	menu := entitys.SysMenu{}
	where := &entitys.SysMenu{Id: id}
	if count, err := repo.BaseRepo.DeleteByWhere(&menu, where); err != nil {
		repo.Log.Errorf("删除菜单失败", err)
		return false
	} else {
		return count > 0
	}
}

func (repo *SysMenuRepo) ListMenu(page, size int32, total *int32, where any) []*entitys.SysMenu {
	var menus []*entitys.SysMenu
	if err := repo.BaseRepo.GetPages(&entitys.SysMenu{}, &menus, page, size, total, where).Error; err != nil {
		repo.Log.Errorf("获取菜单列表失败", err)
	}
	return menus
}

func (repo *SysMenuRepo) GetMenuByRoleId(roleId int32) []*entitys.SysMenu {
	var menus []*entitys.SysMenu
	err := repo.BaseRepo.Source.DB().Raw("select m.* from sys_menu m, sys_role_menu rm where m.menu_id = rm.menu_id and rm.role_id = ?", roleId).Find(&menus).Error
	if err != nil {
		repo.Log.Errorf("查询数据失败", err)
	}
	return menus
}

func (repo *SysMenuRepo) GetMenuIdByRoleId(roleId int32) []int32 {
	var menuIds []int32
	if err := repo.BaseRepo.Source.DB().Table("sys_role_menu").Where("role_id = ?", roleId).Pluck("menu_id", &menuIds).Error; err != nil {
		repo.Log.Errorf("查询数据失败", err)
	}
	return menuIds
}

func (repo *SysMenuRepo) GetMenuIdByUserId(userId int32) []int32 {
	var menuIds []int32
	rows, err := repo.BaseRepo.Source.DB().Raw("select distinct rm.menu_id from sys_user_role ur, sys_role_menu rm where ur.role_id = rm.role_id and ur.user_id = ?", userId).Rows()
	if err != nil {
		repo.Log.Errorf("查询数据失败", err)
		return menuIds
	}
	defer rows.Close()
	for rows.Next() {
		var menuId int32
		_ = rows.Scan(&menuId)
		menuIds = append(menuIds, menuId)
	}
	return menuIds
}

func (repo *SysMenuRepo) GetMenuPermByUserId(userId int32) []string {
	var perms []string
	rows, err := repo.BaseRepo.Source.DB().Raw("select distinct m.perm from sys_menu m, sys_user_role ur, sys_role_menu rm where ur.role_id = rm.role_id and rm.menu_id = m.menu_id and m.is_del = 0 and ur.user_id = ?", userId).Rows()
	if err != nil {
		repo.Log.Errorf("查询数据失败", err)
		return perms
	}
	defer rows.Close()
	for rows.Next() {
		var perm string
		_ = rows.Scan(&perm)
		perms = append(perms, perm)
	}
	return perms
}

func (repo *SysMenuRepo) GetMenusByPid(pid int32) []*entitys.SysMenu {
	var menus []*entitys.SysMenu
	if err := repo.BaseRepo.Source.DB().Where("parent_menu_id = ?", pid).Find(&menus).Error; err != nil {
		repo.Log.Errorf("查询数据失败", err)
	}
	return menus
}

func (repo *SysMenuRepo) SaveMenuApi(menuId int32, apiId int32) bool {
	if err := repo.BaseRepo.Source.DB().Exec("insert into sys_menu_api(menu_id, api_id) values (?, ?)", menuId, apiId).Error; err != nil {
		repo.Log.Errorf("写入数据失败", err)
		return false
	}
	return true
}

func (repo *SysMenuRepo) DelMenuApi(menuId int32) bool {
	if err := repo.BaseRepo.Source.DB().Exec("delete from sys_menu_api where menu_id = ?", menuId).Error; err != nil {
		repo.Log.Errorf("删除数据失败", err)
		return false
	}
	return true
}

func (repo *SysMenuRepo) GetApiIdByMenuId(menuId int32) []int32 {
	var apiIds []int32
	if err := repo.BaseRepo.Source.DB().Table("sys_menu_api").Where("menu_id = ?", menuId).Pluck("api_id", &apiIds).Error; err != nil {
		repo.Log.Errorf("查询数据失败", err)
	}
	return apiIds
}
